/**
 * 问题：类组件中可以使用 PureComponent 来实现性能优化，函数式组件如何实现性能优化
 * 答案：React.memo() 高阶函数，包装下 函数式组件。
 *
 * 问题：当 App是一个函数式组件时，里面定义了一个函数且将这个函数传递给了做好优化的子组件。
 *      但是优化好没有生效。
 * 原因：当 App更新的时候，会重新生成一个 fn1 函数，传递给 Hello 组件，导致 Hello 中判断props是否变化有误。、
 * 解决方案：App 中的 fn1 函数，使用 useCallback 这个 hook 处理下即可。
 *
 *
 * useCallback
 *    接受两个参数
 *        1. 一个函数
 *        2. 一个依赖项数组
 *    返回值时一个函数
 *
 *    返回值的这个函数有什么特点：
 *        1. 有缓存。当前函数式组件重新执行时，不会生成新的函数
 */
import React, { useCallback, useState } from "react";
import ReactDOM from "react-dom/client";

/**
 * 当前代码使用了PureComponent之后，Hello 组件每次要更新的时候，内部都做了props的浅比较。
 * 如果 props 没有发生变化，则阻止更新流程，不会执行render
 * 如果 props 发生变化，就不会阻止更新流程，会执行render
 *
 * 初次渲染 Hello 收到的 props 为 {name: '张三'}
 * 当 App 组件的 name 修改时，这时我们 Hello 收到的 props 为 {name: '张三1'} 与上一次的props比较，发现需要更新。
 * 当 App 组件的 age 修改时，这时我们 Hello 收到的 props 为 {name: '张三'} 与上一次的props比较，发现不需要更新。
 *
 *
 * {name: '张三', fn: () => {}}
 * {name: '张三1', fn: () => {}}
 * {name: '张三', fn: () => {}}
 */
// class Hello extends React.PureComponent {
//   render() {
//     console.log("hello render");
//     return (
//       <div>
//         <h1>Hello</h1>
//         <p>props.name = {this.props.name}</p>
//       </div>
//     );
//   }
// }

function Hello(props) {
  console.log("Hello");
  return (
    <div>
      <h1>Hello</h1>
      <p>props.name = {props.name}</p>
    </div>
  );
}

// 使用 React.memo 包装 Hello 组件，之后，返回一个新组件，取名我还是叫Hello
Hello = React.memo(Hello);

function App() {
  const [name, setName] = useState("张三");
  const [age, setAge] = useState(18);

  // 这个fn1函数，当App函数重新执行时，都会生成一个新的fn1
  // const fn1 = () => {
  //   console.log(1);
  // };

  // 这里的 fn1 函数，应该 useCallback 处理了，
  // 当 App 重新执行时，这个 fn1 取的是上一次的缓存函数，也就是没有新生成函数
  const fn1 = useCallback(() => {
    console.log(1);
  }, []);

  return (
    <div>
      <h1>App</h1>
      <button onClick={() => setName((prevName) => prevName + 1)}>
        修改 name
      </button>
      <button onClick={() => setAge((prevAge) => prevAge + 1)}>修改 age</button>

      <Hello name={name} fn={fn1} />
    </div>
  );
}

const root = ReactDOM.createRoot(document.querySelector("#root"));
root.render(<App />);
